#include "serverTrans.h"

int recvn(int sockfd,void *buf,int length )
{
    int total = 0;
    char* p =(char*)buf;
    while(total<length)
    {
        ssize_t sret = recv(sockfd,p+total,length-total,0);
        if(sret == 0)
        {
            printf("客户端退出\n");
            return 0;
        }
        total += sret;
    }
    return total;
}

int get_s(int netfd ,char *filename)
{
    train_t train;
    bzero(&train,sizeof(train));
    train.tag = 4;

    //接收文件名
    /* char filename[1024] = {0}; */
    /* recv(netfd,&train.tag,sizeof(int),MSG_WAITALL); */ 
    /* recv(netfd,&train.length,sizeof(int),MSG_WAITALL); */
    /* recv(netfd,filename,train.length,MSG_WAITALL); */

    printf("fliename = %s\n",filename);

    //接收偏移值
    off_t offset;
    recv(netfd,&train.tag,sizeof(int),MSG_WAITALL); 
    recv(netfd,&train.length,sizeof(int),MSG_WAITALL);
    recv(netfd,&offset,train.length,MSG_WAITALL);
    printf("offset = %ld\n",offset);

    int fd = open(filename,O_RDWR);
    ERROR_CHECK(fd,-1,"open");

    //发送文件大小
    struct stat statbuf;
    fstat(fd,&statbuf);

    off_t filesize = statbuf.st_size;

    train.length = sizeof(filesize);
    memcpy(train.data,&filesize,sizeof(filesize));
    send(netfd,&train,sizeof(int)+sizeof(int)+train.length,MSG_NOSIGNAL);
    printf("filesize = %ld\n",filesize);

    printf("发送中...\n");
    if(filesize>100*1024*1024)
    {
        //发送大文件
        char* p = (char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ssize_t sret = send(netfd,p+offset,filesize-offset,MSG_NOSIGNAL);
        munmap(p,filesize);

        printf("sret = %ld\n",sret);
    }
    else
    {
        //发送小文件
        lseek(fd,offset,SEEK_SET);
        while(offset<filesize)
        {
            ssize_t sret = read(fd,train.data,sizeof(train.data));
            train.length = sret;
            send(netfd,&train,sizeof(int)+sizeof(int)+train.length,MSG_NOSIGNAL);
            offset += sret;
        } 
    }
    printf("发送完毕\n");
    close(fd);
    return 0;
}


int put_s(int netfd,char*filename)
{
    //准备小火车
    train_t train;
    bzero(&train,sizeof(train));
    train.tag = 4;

    //接收文件名
    /* char filename[1024] = {0}; */
    /* recv(netfd,&train.tag,sizeof(int),MSG_WAITALL); */
    /* recv(netfd,&train.length,sizeof(int),MSG_WAITALL); */
    /* recv(netfd,filename,train.length,MSG_WAITALL); */

    printf("fliename = %s\n",filename);


    printf("offset before\n");
    //接收文件大小
    off_t filesize;
    recv(netfd,&train.tag,sizeof(int),0);
    printf("tag = %d\n",train.tag);
    recv(netfd,&train.length,sizeof(int),0);
    recv(netfd,&filesize,train.length,0);
    printf("filesize = %ld\n",filesize);

    printf("********************\n");
    //拼接文件名
    int len = strlen(".filepart");
    len += strlen(filename);
    char *filepart = (char*)calloc(len+1,1);
    strcpy(filepart,filename);
    strcat(filepart,".filepart");
    printf("%s\n",filepart);

    //打开文件
    int fd = open(filepart,O_RDWR|O_CREAT|O_APPEND,0666);
    ERROR_CHECK(fd,-1,"open");

    //发送偏移值
    struct stat stat_buf;
    fstat(fd,&stat_buf);
    //偏移值
    off_t offset = stat_buf.st_size;//文件大小为不为0,说明之前下载过
    train.tag = 4;
    train.length = sizeof(off_t);
    memcpy(train.data,&offset,sizeof(offset));
    send(netfd,&train,sizeof(int)+sizeof(int)+train.length,MSG_NOSIGNAL);
    printf("offset = %ld\n",offset);

    //接收文件
    printf("上传中...\n");
    if(filesize>100*1024*1024)
    {
        //接收大文件
        ftruncate(fd,filesize);
        char* p = (char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ssize_t sret = recv(netfd,p+offset,filesize-offset,MSG_WAITALL);
        printf("sret = %ld\n",sret);
        ERROR_CHECK(sret,-1,"recv");
        offset += sret;
        munmap(p,filesize);
    }
    else
    {
        //接收小文件
        lseek(fd,offset,SEEK_SET);
        while(offset<filesize)
        {
            int len;
            if(filesize - offset>1000)
            {
                len = 1000;
            }
            else
            {
                len = filesize - offset;
            }
            bzero(&train,sizeof(train));
            recv(netfd,&train.tag,sizeof(int),MSG_WAITALL);
            recv(netfd,&train.length,sizeof(int),MSG_WAITALL);
            /* ssize_t sret = recv(netfd,train.data,train.length,MSG_WAITALL); */
            ssize_t sret = recvn(netfd,train.data,train.length);
            if(sret < len)
            {
                printf("客户端退出\n");
                printf("上传失败\n");
                close(fd);
                return 0;
            }
            write(fd,train.data,sret);
            offset += sret;
        }
        printf("上传成功\n");
        rename(filepart,filename);
        close(fd);
        return 0;
    }

    if(offset == filesize)
    {
        rename(filepart,filename);
        printf("上传成功\n");
    }
    else
    {
        ftruncate(fd,offset);
        printf("上传失败\n");
    }
    close(fd);
    return 0;
}
